package options

import (
	"fmt"

	"github.com/mars/internal/pkg/utils"
	"github.com/spf13/pflag"
)

// MongoOptions 创建一个mongo客户端所需要的配置信息
type MongoOptions struct {
	Addrs                  []string `mapstructure:"addrs"                    json:"addrs"`
	Username               string   `mapstructure:"username"                 json:"username"`
	Password               string   `mapstructure:"password"                 json:"-"`
	Database               string   `mapstructure:"database"                 json:"database"`
	ServerSelectionTimeout int64    `mapstructure:"server-selection-timeout" json:"server-selection-timeout"`
	SocketTimeout          int64    `mapstructure:"socket-timeout"           json:"socket-timeout"` // 请求mongo如果超过SocketTimeout没有数据响应，则认为超时并且报错
	ConnectTimeout         int64    `mapstructure:"connect-timeout"          json:"connect-timeout"`
	MaxConnIdleTime        int64    `mapstructure:"max-conn-idel-time"       json:"max-conn-idel-time"`
	PoolSize               int      `mapstructure:"pool-size"                json:"pool-size"`
}

func NewMongoOptions() *MongoOptions {
	return &MongoOptions{
		Addrs:                  []string{"127.0.0.1:27017"},
		Username:               "",
		Password:               "",
		Database:               "",
		SocketTimeout:          5,
		ServerSelectionTimeout: 5,
		ConnectTimeout:         10,
		MaxConnIdleTime:        60,
		PoolSize:               100,
	}
}

func (opts *MongoOptions) AddFlags(fs *pflag.FlagSet) {
	fs.StringArrayVar(&opts.Addrs, "mongo.addrs", opts.Addrs, "Specify Mongo service connect addrs.")
	fs.StringVar(&opts.Username, "mongo.username", opts.Username, "Specify Mongo service login username.")
	fs.StringVar(&opts.Password, "mongo.password", opts.Password, "Specify Mongo service login password.")
	fs.StringVar(&opts.Database, "mongo.database", opts.Database, "Specify Mongo service database.")
	fs.Int64Var(&opts.SocketTimeout, "mongo.socket-timeout", opts.SocketTimeout, "Specify mongo service socket timeout,unit second.")
	fs.Int64Var(&opts.ServerSelectionTimeout, "mongo.server-selection-timeout", opts.ServerSelectionTimeout, "Specify mongo service ServerSelectionTimeout,unit second.")
	fs.Int64Var(&opts.ConnectTimeout, "mongo.connect-timeout", opts.ConnectTimeout, "Specify mongo service connect timeout,unit second.")
	fs.Int64Var(&opts.MaxConnIdleTime, "mongo.max-conn-idel-time", opts.MaxConnIdleTime, "Specify the maximum amount of time that a connection will remain idle in a connection pool before it is removed from the pool and closed,unit second.")
	fs.IntVar(&opts.PoolSize, "mongo.pool-size", opts.PoolSize, "Specify that maximum number of connections allowed in the driver's connection pool to each server.")
}

func (opts *MongoOptions) Validate() []error {
	var errors = []error{}
	if (len(opts.Username) == 0 || len(opts.Password) == 0) && len(opts.Username+opts.Password) != 0 {
		errors = append(errors, fmt.Errorf("--mongo.username and --mongo.password should be both empty or not empty"))
	}

	if len(opts.Password) > 0 {
		clear, err := utils.Decrypt(opts.Password)
		if err != nil {
			errors = append(errors, err)
		}
		opts.Password = clear
	}
	return errors
}
